package maquina_virtual;

import java.util.Stack;
import instrucciones.Apila;
import instrucciones.ApilaDir;
import instrucciones.ApilaIndirecto;
import instrucciones.CambiaSigno;
import instrucciones.ComparaDistinto;
import instrucciones.ComparaIgual;
import instrucciones.ComparaMayor;
import instrucciones.ComparaMayorIgual;
import instrucciones.ComparaMenor;
import instrucciones.ComparaMenorIgual;
import instrucciones.ConvCaracter;
import instrucciones.ConvEnt;
import instrucciones.ConvNat;
import instrucciones.ConvReal;
import instrucciones.Copia;
import instrucciones.DDerecha;
import instrucciones.DIzquierda;
import instrucciones.Desapila;
import instrucciones.DesapilaDir;
import instrucciones.DesapilaIndirecto;
import instrucciones.Divide;
import instrucciones.EscribeBooleano;
import instrucciones.EscribeCaracter;
import instrucciones.EscribeEntero;
import instrucciones.EscribeNatural;
import instrucciones.EscribeReal;
import instrucciones.Instrucciones;
import instrucciones.LeeBooleano;
import instrucciones.LeeCaracter;
import instrucciones.LeeEntero;
import instrucciones.LeeNatural;
import instrucciones.LeeReal;
import instrucciones.LiberaEspacio;
import instrucciones.Modulo;
import instrucciones.Mueve;
import instrucciones.Multiplica;
import instrucciones.NoLogico;
import instrucciones.OLogica;
import instrucciones.ReservaEspacio;
import instrucciones.Resta;
import instrucciones.SaltoCondicionalF;
import instrucciones.SaltoCondicionalV;
import instrucciones.SaltoIncondicional;
import instrucciones.SaltoIncondicionalCima;
import instrucciones.Suma;
import instrucciones.YLogica;

public class InterpreteP {
	/*Atributos*/
		private int cProg;
		private Stack<Number> pila;
		private boolean parada;
		private MemoriaInstrucciones memins;
		private MemoriaDatos memdata;
		private boolean modotraza;

	/*Constructora*/
		public InterpreteP(MemoriaInstrucciones memins,boolean modotraza){
			this.cProg=0;
			this.pila=new Stack<Number>();
			this.parada=false;
			this.memins= memins;
			this.memdata= new MemoriaDatos();
			this.modotraza=modotraza;
		}

	/*Metodos*/
		public void principal () throws Exception
		{
			while (!parada){
				Instrucciones ins = analizaLinea(memins.getInstruccion(cProg));
				if (modotraza){
					System.out.println(pila);
					memdata.imprime();
					System.in.read();
					System.out.println(memins.getInstruccion(cProg));
				}
				if (!parada) ins.ejecuta(pila, cProg, memdata);
				cProg++;
			}
		}

		public Instrucciones analizaLinea(String linea)
		{
			if (linea.startsWith("apila ")) return new Apila(linea.substring(6));
			if (linea.equals("desapila ")) return new Desapila();
			if (linea.startsWith("apila-dir")) return new ApilaDir(linea.substring(10));
			if (linea.startsWith("desapila-dir")) return new DesapilaDir(linea.substring(13));
			if (linea.equals("apila-ind")) return new ApilaIndirecto();
			if (linea.equals("desapila-ind")) return new DesapilaIndirecto();
			if (linea.equals("copia")) return new Copia();
			
			//repertorio de instrucciones nivel0
			if (linea.equals("compara_menor")) return new ComparaMenor();
			if (linea.equals("compara_mayor")) return new ComparaMayor();
			if (linea.equals("compara_menorigual")) return new ComparaMenorIgual();
			if (linea.equals("compara_mayorigual")) return new ComparaMayorIgual();
			if (linea.equals("compara_igual")) return new ComparaIgual();
			if (linea.equals("compara_distinto")) return new ComparaDistinto();
			
			//repertorio de instrucciones nivel1
			if (linea.equals("suma")) return new Suma();
			if (linea.equals("resta")) return new Resta();
			if (linea.equals("o_logica")) return new OLogica();

			//repertorio de instrucciones nivel2
			if (linea.equals("multiplica"))return new Multiplica();
			if (linea.equals("divide")) return new Divide();
			if (linea.equals("modulo")) return new Modulo(); 
			if (linea.equals("y_logica")) return new YLogica(); 
						
			//repertorio de instrucciones nivel3
			if (linea.equals("desplaza_derecha")) return new DDerecha(); 
			if (linea.equals("desplaza_izquierda")) return new DIzquierda(); 
			
			//repertorio de instrucciones nivel4
			if (linea.equals("no_logico")) return new NoLogico(); 
			if (linea.equals("cambia_signo")) return new CambiaSigno(); 
			if (linea.equals("convierte_real")) return new ConvReal(); 
			if (linea.equals("convierte_entero")) return new ConvEnt(); 
			if (linea.equals("convierte_natural")) return new ConvNat(); 
			if (linea.equals("convierte_caracter")) return new ConvCaracter(); 
			
			//lectura y escritura
			if (linea.startsWith("lee_booleano")) return new LeeBooleano(linea.substring(12));
			if (linea.startsWith("lee_entero")) return new LeeEntero(linea.substring(10));
			if (linea.startsWith("lee_natural")) return new LeeNatural(linea.substring(11));
			if (linea.startsWith("lee_caracter")) return new LeeCaracter(linea.substring(12));
			if (linea.startsWith("lee_real")) return new LeeReal(linea.substring(8));
			if (linea.equals("escribe_booleano")) return new EscribeBooleano();
			if (linea.equals("escribe_entero")) return new EscribeEntero();
			if (linea.equals("escribe_natural")) return new EscribeNatural();
			if (linea.equals("escribe_caracter")) return new EscribeCaracter();
			if (linea.equals("escribe_real")) return new EscribeReal();
			
			//saltos
			if (linea.startsWith("ir-a")) return new SaltoIncondicional(linea.substring(5));
			if (linea.startsWith("ir-f")) return new SaltoCondicionalF(linea.substring(5));
			if (linea.startsWith("ir-v")) return new SaltoCondicionalV(linea.substring(5));
			if (linea.equals("ir-ind")) return new SaltoIncondicionalCima();
			
			//manipulacion de memoria
			if (linea.startsWith("mueve")) return new Mueve(linea.substring(6));
			if (linea.startsWith("new")) return new ReservaEspacio(linea.substring(4));
			if (linea.startsWith("delete")) return new LiberaEspacio(linea.substring(7));
			
			//stop
			if (linea.equals("stop")) parada=true;
			
			return null;
		}
	
}